/**
 * Copyright (C) 2009 Noel Ang
 *
 * This file is part of Samsara.
 *
 * Samsara is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Samsara is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Samsara.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package com.lunarshades.samsara.ui;

import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import static java.awt.GridBagConstraints.BOTH;
import static java.awt.GridBagConstraints.FIRST_LINE_START;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

/**
 * Controller for posting status events.
 *
 * @author Noel Ang, sparta.variable@gmail.com
 */
class StatusPanel {
StatusPanel(boolean persistentMessages) {
    mPanel = new JPanel();
    initPanel(mPanel);

    if (!persistentMessages) {
        mTimer = new Timer(DELAY, new MessageDisposal());
        mTimer.setRepeats(false);
    } else {
        mTimer = null;
    }
}

private void initPanel(JPanel panel) {
    panel.setLayout(new GridBagLayout());

    GridBagConstraints cons = new GridBagConstraints();
    cons.fill = BOTH;

    // general message area
    JLabel generalArea = new JLabel("");
    cons.insets = new Insets(0, 2, 0, 2);
    cons.gridy = 0;
    cons.anchor = FIRST_LINE_START;
    cons.weightx = 1;
    mPanel.add(generalArea, cons);

    cons.weightx = 0;

    mPanel.add(new JSeparator(SwingConstants.VERTICAL), cons);

    // Logging indicator
    JLabel logArea = new JLabel("Log");
    logArea.setSize(logArea.getPreferredSize());
    logArea.setMinimumSize(logArea.getPreferredSize());
    logArea.setMaximumSize(logArea.getPreferredSize());
    logArea.setToolTipText(LOG_DISABLED_TOOLTIP);
    mLogForeground = logArea.getForeground();
    logArea.setForeground(logArea.getBackground());
    mPanel.add(logArea, cons);

    mPanel.add(new JSeparator(SwingConstants.VERTICAL), cons);

    // Roster size indicator
    StringBuffer buf =
            new StringBuffer(NONE_TEXT).append(" ").append(ENTRIES_TEXT);
    JLabel recordsArea = new JLabel(buf.toString());
    recordsArea.setSize(recordsArea.getPreferredSize());
    recordsArea.setMinimumSize(recordsArea.getPreferredSize());
    recordsArea.setMaximumSize(recordsArea.getPreferredSize());
    recordsArea.setToolTipText(RECORD_TOOLTIP);
    mPanel.add(recordsArea, cons);

    mGeneralArea = generalArea;
    mLogArea = logArea;
    mRecordsArea = recordsArea;
}

private void unpost(String message) {
    if (mTimer != null) {
        mTimer.stop();
        mTimer.setActionCommand(message);
        mTimer.start();
    }
}

protected void post(final String message) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            synchronized (mLock) {
                mGeneralArea.setText(message);
            }
            StatusPanel.this.unpost(message);
        }
    }
    );
}

protected void post(Boolean message) {
    final Boolean msg = message;
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            mLogArea.setForeground(msg
                                   ? mLogForeground
                                   : mLogArea.getBackground()
            );
            mLogArea.setToolTipText(msg
                                    ? LOG_ENABLED_TOOLTIP
                                    : LOG_DISABLED_TOOLTIP);
        }
    }
    );
}

protected void post(Integer message) {
    final Integer msg = message;
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            if (msg.equals(-1)) {
                mRecordsArea.setText("Error");
            } else {
                StringBuffer buf = new StringBuffer(msg.toString());
                buf.append(" ")
                        .append(msg.equals(1) ? ENTRY_TEXT : ENTRIES_TEXT);
                mRecordsArea.setText(buf.toString());
            }
        }
    }
    );

}

public void report(StatusType type, Object message) {
    switch (type) {
    case GENERAL:
        post(String.valueOf(message));
        break;
    case LOG:
        post(Boolean.valueOf(String.valueOf(message)));
        break;
    case DATA_SET_SIZE:
        Integer count;
        try {
            count = Integer.decode(String.valueOf(message));
        } catch (NumberFormatException e) {
            e.printStackTrace(System.err);
            count = -1;
        }
        post(count);
        break;
    default:
    }
}

Component getComponent() {
    return mPanel;
}

private class MessageDisposal implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        synchronized (mLock) {
            String postedMessage = mGeneralArea.getText();
            if (postedMessage.equals(e.getActionCommand())) {
                mGeneralArea.setText("");
            }
        }
    }
}

public static enum StatusType {
    GENERAL, LOG, DATA_SET_SIZE
}

private static final String LOG_ENABLED_TOOLTIP = "Log recording is ACTIVE";
private static final String LOG_DISABLED_TOOLTIP = "Log recording is disabled";
private static final String RECORD_TOOLTIP = "Number of visible entries";
private static final String ENTRY_TEXT = "entry";
private static final String ENTRIES_TEXT = "entries";
private static final String NONE_TEXT = "No";
private static final int DELAY = 10000;

private final Timer mTimer;
private final JPanel mPanel;
private final Object mLock = new Object();
private JLabel mGeneralArea;
private JLabel mLogArea;
private JLabel mRecordsArea;
private volatile Color mLogForeground;
}
